# -*- coding: utf8 -*-
import logging
import re
from datetime import datetime
from enum import Enum

from console.enum.app import GovernanceModeEnum
from console.enum.component_enum import ComponentSource
from console.utils import runner_util
from django.conf import settings
from django.db import models
from django.db.models.fields import (AutoField, BooleanField, CharField, DateTimeField, DecimalField, IntegerField)
from django.db.models.fields.files import FileField
from django.utils.crypto import salted_hmac
from www.utils.crypt import encrypt_passwd, make_tenant_id, make_uuid

logger = logging.getLogger("default")

# Create your models here.

user_origion = (("自主注册", "registration"), ("邀请注册", "invitation"))

tenant_type = (("免费租户", "free"), ("付费租户", "payed"))

service_identity = (("管理员", "admin"), ("开发者", "developer"), ("观察者", "viewer"))

tenant_identity = (("拥有者", "owner"), ("管理员", "admin"), ("开发者", "developer"), ("观察者", "viewer"), ("访问", "access"))

app_pay_choices = (('免费', "free"), ('付费', "pay"))

pay_method = (('预付费提前采购', "prepaid"), ('按使用后付费', "postpaid"))


def compose_file_path(instance, filename):
    suffix = filename.split('.')[-1]
    return '{0}/compose-file/{1}.{2}'.format(settings.MEDIA_ROOT, make_uuid(), suffix)


class AnonymousUser(object):
    id = None
    pk = None
    username = ''
    is_active = False

    def __str__(self):
        return 'AnonymousUser'

    def __eq__(self, other):
        return isinstance(other, self.__class__)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __hash__(self):
        return 1  # instances always return the same hash value

    def save(self):
        raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")

    def delete(self):
        raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")

    def set_password(self, raw_password):
        raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")

    def check_password(self, raw_password):
        raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")

    def get_group_permissions(self, obj=None):
        return set()

    def is_anonymous(self):
        return True

    def is_authenticated(self):
        return False


class WeChatConfig(models.Model):
    """微信的accesstoken"""

    class Meta:
        db_table = "wechat_config"

    MOBILE = "mobile"
    WEB = "web"
    BIZ = "biz"
    BIZPLUGIN = "bizplugin"

    OPEN_TYPE = ((MOBILE, "移动应用"), (WEB, "网站应用"), (BIZ, "公众帐号"), (BIZPLUGIN, "公众号第三方平台"))

    config = models.CharField(unique=True, max_length=100, help_text='微信应用的名称')
    app_id = models.CharField(max_length=200, help_text='app_id')
    app_secret = models.CharField(max_length=200, help_text='app_secret')
    token = models.CharField(max_length=200, help_text='token')
    encrypt_mode = models.CharField(max_length=200, help_text='encrypt_mode')
    encoding_aes_key = models.CharField(max_length=200, help_text='aes_key')
    access_token = models.CharField(max_length=200, help_text='access_token')
    access_token_expires_at = models.IntegerField(help_text="token过期时间")
    refresh_token = models.CharField(max_length=200, help_text='refresh_token,只对网页授权有效')
    app_type = models.CharField(max_length=200, choices=OPEN_TYPE, help_text='公众平台or网站')


class WeChatUser(models.Model):
    """微信用户表格"""

    class Meta:
        db_table = "wechat_user_info"

    open_id = models.CharField(primary_key=True, max_length=200, help_text='微信用户open_id')
    nick_name = models.CharField(max_length=100, help_text="微信用户昵称")
    sex = models.IntegerField(help_text='性别')
    city = models.CharField(max_length=100, help_text='城市')
    province = models.CharField(max_length=100, help_text='省地区')
    country = models.CharField(max_length=100, help_text='国家')
    headimgurl = models.CharField(max_length=200, help_text='头像')
    union_id = models.CharField(max_length=200, help_text='微信用户union_id')
    config = models.CharField(max_length=100, help_text='所属的微信应用')

    def is_authenticated(self):
        return True

    @property
    def is_sys_admin(self):
        admins = ('ertyuiofghjklasdfas', )
        return bool(self.unionid in admins)

    def get_session_auth_hash(self):
        key_salt = "goodrain.com.models.get_session_auth_hash"
        return salted_hmac(key_salt, self.user_id).hexdigest()

    def to_dict(self):
        opts = self._meta
        data = {}
        for f in opts.concrete_fields:
            value = f.value_from_object(self)
            if isinstance(value, datetime):
                value = value.strftime('%Y-%m-%d %H:%M:%S')
            data[f.name] = value
        return data


class WeChatUnBind(models.Model):
    """解绑用户的映射关系"""

    class Meta:
        db_table = 'wechat_unbind'

    user_id = models.IntegerField(help_text="用户的user_id")
    union_id = models.CharField(max_length=200, help_text='微信用户union_id')
    status = models.IntegerField(help_text='用户解绑的状态')


class WeChatState(models.Model):
    """微信state过长存储表格"""

    class Meta:
        db_table = 'wechat_state'

    ID = models.AutoField(primary_key=True, max_length=10)
    state = models.CharField(max_length=5000, help_text='微信登录state')
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    update_time = models.DateTimeField(auto_now=True, help_text="更新时间")

    def to_dict(self):
        opts = self._meta
        data = {}
        for f in opts.concrete_fields:
            value = f.value_from_object(self)
            if isinstance(value, datetime):
                value = value.strftime('%Y-%m-%d %H:%M:%S')
            data[f.name] = value
        return data


class SuperAdminUser(models.Model):
    """超级管理员"""

    class Meta:
        db_table = "user_administrator"

    user_id = models.IntegerField(unique=True, help_text="用户ID")
    email = models.EmailField(max_length=35, null=True, blank=True, help_text="邮件地址")


class Users(models.Model):
    USERNAME_FIELD = 'nick_name'

    class Meta:
        db_table = 'user_info'

    user_id = models.AutoField(primary_key=True, max_length=10)
    email = models.EmailField(max_length=35, help_text="邮件地址")
    nick_name = models.CharField(max_length=64, null=True, blank=True, help_text="账号")
    real_name = models.CharField(max_length=64, null=True, blank=True, help_text="姓名")
    password = models.CharField(max_length=64, help_text="密码")
    phone = models.CharField(max_length=15, null=True, blank=True, help_text="手机号码")
    is_active = models.BooleanField(default=False, help_text="激活状态")
    origion = models.CharField(max_length=12, choices=user_origion, help_text="用户来源")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    git_user_id = models.IntegerField(help_text="gitlab 用户id", default=0)
    github_token = models.CharField(max_length=60, help_text="github token")
    client_ip = models.CharField(max_length=20, help_text="注册ip")
    rf = models.CharField(max_length=60, help_text="register from")
    # 0:普通注册,未绑定微信
    # 1:普通注册,绑定微信
    # 2:微信注册,绑定微信,未补充信息
    # 3:微信注册,绑定微信,已补充信息
    # 4:微信注册,解除微信绑定,已补充信息
    status = models.IntegerField(default=0, help_text='用户类型 0:普通注册,未绑定微信')
    union_id = models.CharField(max_length=100, help_text='绑定微信的union_id')
    sso_user_id = models.CharField(max_length=32, null=True, blank=True, default='', help_text="统一认证中心的user_id")
    sso_user_token = models.CharField(max_length=256, null=True, blank=True, default='', help_text="统一认证中心的user_id")
    enterprise_id = models.CharField(max_length=32, null=True, blank=True, default='', help_text="统一认证中心的enterprise_id")
    enterprise_center_user_id = models.CharField(max_length=32, null=True, blank=True, default='', help_text="统一认证中心的user id")

    def set_password(self, raw_password):
        self.password = encrypt_passwd(self.email + raw_password)

    def check_password(self, raw_password):
        return bool(encrypt_passwd(self.email + raw_password) == self.password)

    def is_anonymous(self):
        return False

    def is_authenticated(self):
        return True

    def get_name(self):
        if self.real_name:
            return self.real_name
        return self.nick_name

    @property
    def is_sys_admin(self):
        """
        是否是系统管理员
        :return: True/False
        """
        if self.user_id:
            try:
                SuperAdminUser.objects.get(user_id=self.user_id)
                return True
            except SuperAdminUser.DoesNotExist:
                pass
        return False

    def get_session_auth_hash(self):
        """
        Returns an HMAC of the password field.
        """
        key_salt = "goodrain.com.models.get_session_auth_hash"
        return salted_hmac(key_salt, self.password).hexdigest()

    @property
    def safe_email(self):
        return re.sub(r'(?<=\w{2}).*(?=\w@.*)', 'xxxx', self.email)

    def __unicode__(self):
        return self.nick_name or self.email

    def to_dict(self):
        opts = self._meta
        data = {}
        for f in opts.concrete_fields:
            value = f.value_from_object(self)
            if isinstance(value, datetime):
                value = value.strftime('%Y-%m-%d %H:%M:%S')
            data[f.name] = value
        return data

    def get_username(self):
        return self.nick_name


class BaseModel(models.Model):
    class Meta:
        abstract = True

    ID = models.AutoField(primary_key=True, max_length=10)

    def to_dict(self):
        opts = self._meta
        data = {}
        for f in opts.concrete_fields:
            value = f.value_from_object(self)
            if isinstance(value, datetime):
                value = value.strftime('%Y-%m-%d %H:%M:%S')
            elif isinstance(f, FileField):
                value = value.url if value else None
            data[f.name] = value
        return data

    def to_json(self):
        opts = self._meta
        data = []
        for f in opts.concrete_fields:
            parameter = {}
            parameter["table"] = opts.db_table
            parameter["name"] = f.name
            parameter["kind"] = self.parse_kind(f)
            parameter["default"] = self.parse_default(f.default)
            parameter["desc"] = f.help_text
            data.append(parameter)
        return data

    def parse_default(self, a):
        # if type(a) == NOT_PROVIDED:
        return ""

    def parse_kind(self, a):
        # print(a.name, type(a))
        if type(a) == CharField:
            return "string"
        if type(a) == AutoField:
            return "int"
        if type(a) == BooleanField:
            return "boolean"
        if type(a) == DecimalField:
            return "decimal"
        if type(a) == DateTimeField:
            return "datetime"
        if type(a) == IntegerField:
            return "int"
        return "string"


class Tenants(BaseModel):
    """
    租户表
    """

    class Meta:
        db_table = 'tenant_info'

    tenant_id = models.CharField(max_length=33, unique=True, default=make_tenant_id, help_text="租户id")
    tenant_name = models.CharField(max_length=64, unique=True, help_text="租户名称")
    # This property is deprecated
    # region = models.CharField(max_length=64, default='', help_text="区域中心,弃用")
    is_active = models.BooleanField(default=True, help_text="激活状态")
    pay_type = models.CharField(max_length=5, choices=tenant_type, help_text="付费状态")
    balance = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, help_text="账户余额")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    creater = models.IntegerField(help_text="租户创建者", default=0)
    limit_memory = models.IntegerField(help_text="内存大小单位（M）", default=1024)
    update_time = models.DateTimeField(auto_now=True, help_text="更新时间")
    pay_level = models.CharField(max_length=30, default='free', help_text="付费级别:free,personal,company")
    expired_time = models.DateTimeField(null=True, help_text="过期时间")
    tenant_alias = models.CharField(max_length=64, null=True, blank=True, default='', help_text="团队别名")
    enterprise_id = models.CharField(max_length=32, null=True, blank=True, default='', help_text="企业id")

    def __unicode__(self):
        return self.tenant_name


class TenantRegionInfo(BaseModel):
    class Meta:
        db_table = 'tenant_region'
        unique_together = (('tenant_id', 'region_name'), )

    tenant_id = models.CharField(max_length=33, db_index=True, help_text="租户id")
    region_name = models.CharField(max_length=64, help_text="集群ID")
    is_active = models.BooleanField(default=True, help_text="是否已激活")
    is_init = models.BooleanField(default=False, help_text='是否创建租户网络')
    service_status = models.IntegerField(help_text="组件状态0:暂停，1:运行，2:关闭", default=1)
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    update_time = models.DateTimeField(auto_now=True, help_text="更新时间")
    region_tenant_name = models.CharField(max_length=64, null=True, blank=True, default='', help_text="数据中心租户名")
    region_tenant_id = models.CharField(max_length=32, null=True, blank=True, default='', help_text="数据中心租户id")
    region_scope = models.CharField(max_length=32, null=True, blank=True, default='', help_text="数据中心类型 private/public")
    enterprise_id = models.CharField(max_length=32, null=True, blank=True, default='', help_text="企业id")


class TenantRegionResource(BaseModel):
    class Meta:
        db_table = 'tenant_region_resource'
        unique_together = (('tenant_id', 'region_name'), )

    enterprise_id = models.CharField(max_length=32, help_text="企业id")
    tenant_id = models.CharField(max_length=33, help_text="租户id")
    region_name = models.CharField(max_length=64, help_text="区域中心名称")
    memory_limit = models.IntegerField(help_text="内存使用上限(M)", default=0)
    memory_expire_date = models.DateTimeField(null=True, blank=True, help_text="内存有效期时间")
    disk_limit = models.IntegerField(help_text="磁盘使用上限(M)", default=0)
    disk_expire_date = models.DateTimeField(null=True, blank=True, help_text="磁盘有效期时间")
    net_limit = models.IntegerField(help_text="磁盘使用上限(M)", default=0)
    net_stock = models.IntegerField(help_text="磁盘使用余量(M)", default=0)
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    update_time = models.DateTimeField(auto_now=True, help_text="更新时间")


service_status = (
    ("已发布", 'published'),
    ("测试中", "test"),
)

service_category = (("应用", 'application'), ("缓存", 'cache'), ("存储", 'store'))

extend_method = (("不伸缩", 'stateless'), ("垂直伸缩", 'vertical'))


class ServiceInfo(BaseModel):
    """ 组件发布表格 """

    class Meta:
        db_table = 'service'
        unique_together = ('service_key', 'version')

    service_key = models.CharField(max_length=32, help_text="组件key")
    publisher = models.EmailField(max_length=35, help_text="邮件地址")
    service_name = models.CharField(max_length=100, help_text="组件发布名称")
    pic = models.CharField(max_length=100, null=True, blank=True, help_text="logo")
    info = models.CharField(max_length=100, null=True, blank=True, help_text="简介")
    desc = models.CharField(max_length=400, null=True, blank=True, help_text="描述")
    status = models.CharField(max_length=15, choices=service_status, help_text="组件状态：发布后显示还是隐藏")
    category = models.CharField(max_length=15, help_text="组件分类：application,cache,store")
    is_service = models.BooleanField(default=False, blank=True, help_text="是否inner组件")
    is_web_service = models.BooleanField(default=False, blank=True, help_text="是否web组件")
    version = models.CharField(max_length=20, null=False, help_text="当前最新版本")
    update_version = models.IntegerField(default=1, help_text="内部发布次数")
    image = models.CharField(max_length=200, help_text="镜像")
    namespace = models.CharField(max_length=100, default='', help_text="镜像发布云帮的区间")
    slug = models.CharField(max_length=200, help_text="slug包路径", default="")
    extend_method = models.CharField(max_length=15, choices=extend_method, default='stateless', help_text="伸缩方式")
    cmd = models.CharField(max_length=2048, null=True, blank=True, help_text="启动参数")
    setting = models.CharField(max_length=200, null=True, blank=True, help_text="设置项")
    env = models.CharField(max_length=200, null=True, blank=True, help_text="环境变量")
    dependecy = models.CharField(max_length=100, default="", help_text="依赖组件--service_key待确认")
    min_node = models.IntegerField(help_text="启动个数", default=1)
    min_cpu = models.IntegerField(help_text="cpu个数", default=500)
    min_memory = models.IntegerField(help_text="内存大小单位（M）", default=256)
    inner_port = models.IntegerField(help_text="内部端口", default=0)
    publish_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    volume_mount_path = models.CharField(max_length=200, null=True, blank=True, help_text="mount目录")
    service_type = models.CharField(max_length=50, null=True, blank=True, help_text="组件类型:web,mysql,redis,mongodb,phpadmin")
    is_init_accout = models.BooleanField(default=False, blank=True, help_text="是否初始化账户")
    creater = models.IntegerField(null=True, help_text="创建人")
    publish_type = models.CharField(max_length=10, default="single", help_text="判断组件是否属于组")

    def is_slug(self):
        return bool(runner_util.is_runner(self.image))

    def is_image(self):
        return not self.is_slug()


class TenantServiceInfo(BaseModel):
    class Meta:
        db_table = 'tenant_service'
        unique_together = ('tenant_id', 'service_alias')

    service_id = models.CharField(max_length=32, unique=True, help_text="组件id")
    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_key = models.CharField(max_length=32, help_text="组件key")
    service_alias = models.CharField(max_length=100, help_text="组件别名")
    service_cname = models.CharField(max_length=100, default='', help_text="组件名")
    service_region = models.CharField(max_length=64, help_text="组件所属区")
    desc = models.CharField(max_length=200, null=True, blank=True, help_text="描述")
    category = models.CharField(max_length=15, help_text="组件分类：application,cache,store")
    service_port = models.IntegerField(help_text="组件端口", default=0)
    is_web_service = models.BooleanField(default=False, blank=True, help_text="是否web组件")
    version = models.CharField(max_length=255, help_text="版本")
    update_version = models.IntegerField(default=1, help_text="内部发布次数")
    image = models.CharField(max_length=200, help_text="镜像")
    cmd = models.CharField(max_length=2048, null=True, blank=True, help_text="启动参数")
    min_node = models.IntegerField(help_text="实例数量", default=1)
    min_cpu = models.IntegerField(help_text="cpu分配额 1000=1core", default=500)
    container_gpu = models.IntegerField(help_text="gpu显存数量", default=0)
    min_memory = models.IntegerField(help_text="内存大小单位（M）", default=256)

    # deprecated
    setting = models.CharField(max_length=200, null=True, blank=True, help_text="设置项")
    extend_method = models.CharField(
        max_length=32, choices=extend_method, default='stateless_multiple', help_text="组件部署类型,stateless or state")
    # deprecated
    env = models.CharField(max_length=200, null=True, blank=True, help_text="环境变量")
    # deprecated
    inner_port = models.IntegerField(help_text="内部端口", default=0)
    # deprecated
    volume_mount_path = models.CharField(max_length=200, null=True, blank=True, help_text="mount目录")
    # deprecated
    host_path = models.CharField(max_length=300, null=True, blank=True, help_text="mount目录")
    # deprecated
    deploy_version = models.CharField(max_length=20, null=True, blank=True, help_text="仅用于云市创建应用表示构建源的部署版版-小版本")
    code_from = models.CharField(max_length=20, null=True, blank=True, help_text="代码来源:gitlab,github")
    git_url = models.CharField(max_length=2047, null=True, blank=True, help_text="code代码仓库")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    git_project_id = models.IntegerField(help_text="gitlab 中项目id", default=0)
    # deprecated
    is_code_upload = models.BooleanField(default=False, blank=True, help_text="是否上传代码")
    # deprecated
    code_version = models.CharField(max_length=100, null=True, blank=True, help_text="代码版本")
    service_type = models.CharField(max_length=50, null=True, blank=True, help_text="组件类型:web,mysql,redis,mongodb,phpadmin")
    creater = models.IntegerField(help_text="组件创建者", default=0)
    language = models.CharField(max_length=40, null=True, blank=True, help_text="代码语言")
    # deprecated
    protocol = models.CharField(max_length=15, default='', help_text="服务协议：http,stream")
    # deprecated
    total_memory = models.IntegerField(help_text="内存使用M", default=0)
    # deprecated
    is_service = models.BooleanField(default=False, blank=True, help_text="是否inner组件")
    # deprecated
    namespace = models.CharField(max_length=100, default='', help_text="镜像发布云帮的区间")
    # deprecated
    volume_type = models.CharField(max_length=64, default='shared', help_text="共享类型shared、exclusive")
    # deprecated
    port_type = models.CharField(max_length=15, default='multi_outer', help_text="端口类型，one_outer;dif_protocol;multi_outer")
    # 组件创建类型,cloud、assistant
    service_origin = models.CharField(max_length=15, default='assistant', help_text="组件创建类型cloud云市组件,assistant云帮组件")
    # 组件所属关系，从模型安装的多个组件所属一致。
    tenant_service_group_id = models.IntegerField(default=0, help_text="组件归属的组件组id，从应用模版安装的组件该字段需要赋值")
    # deprecated
    expired_time = models.DateTimeField(null=True, help_text="过期时间")
    open_webhooks = models.BooleanField(default=False, help_text='是否开启自动触发部署功能（兼容老版本组件）')
    service_source = models.CharField(
        max_length=15, default="", null=True, blank=True, help_text="组件来源(source_code, market, docker_run, docker_compose)")
    create_status = models.CharField(max_length=15, null=True, blank=True, help_text="组件创建状态 creating|complete")
    update_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="更新时间")
    check_uuid = models.CharField(max_length=36, blank=True, null=True, default="", help_text="组件检测ID")
    check_event_id = models.CharField(max_length=32, blank=True, null=True, default="", help_text="组件检测事件ID")
    docker_cmd = models.CharField(max_length=1024, null=True, blank=True, help_text="镜像创建命令")
    secret = models.CharField(max_length=64, null=True, blank=True, help_text="webhooks验证密码")
    server_type = models.CharField(max_length=5, default='git', help_text="源码仓库类型")
    is_upgrate = models.BooleanField(default=False, help_text='是否可以更新')
    build_upgrade = models.BooleanField(default=True, help_text='组件构建后是否升级')
    service_name = models.CharField(max_length=100, default='', help_text="组件名称（新加属性，数据中心使用）")
    oauth_service_id = models.IntegerField(default=None, null=True, blank=True, help_text="拉取源码所用的OAuth服务id")
    git_full_name = models.CharField(max_length=64, null=True, blank=True, default=None, help_text="git项目的fullname")

    def __unicode__(self):
        return self.service_alias

    def toJSON(self):
        data = {}
        for f in self._meta.fields:
            obj = getattr(self, f.name)
            if type(f.name) == DateTimeField:
                data[f.name] = obj.strftime('%Y-%m-%d %H:%M:%S')
            else:
                data[f.name] = obj
        return data

    @property
    def component_id(self):
        return self.service_id

    @property
    def upgrade_group_id(self):
        return self.tenant_service_group_id

    @property
    def clone_url(self):
        if self.code_from == "github":
            code_user = self.git_url.split("/")[3]
            code_project_name = self.git_url.split("/")[4].split(".")[0]
            createUser = Users.objects.get(user_id=self.creater)
            git_url = "https://{github_token}@github.com/{code_user}/{code_project_name}.git".format(
                github_token=createUser.github_token, code_user=code_user, code_project_name=code_project_name)
            return git_url
        else:
            return self.git_url

    def is_slug(self):
        return bool(self.image.endswith('/runner')) or bool('/runner:' in self.image)

    def is_third_party(self):
        if self.service_source == ComponentSource.THIRD_PARTY.value:
            return True
        return False

    def calculate_min_cpu(self, min_memory):
        # The algorithm is absolete
        min_cpu = int(min_memory) / 128 * 20
        return int(min_cpu)


class TenantServiceInfoDelete(BaseModel):
    class Meta:
        db_table = 'tenant_service_delete'

    service_id = models.CharField(max_length=32, unique=True, help_text="组件id")
    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_key = models.CharField(max_length=32, help_text="组件key")
    service_alias = models.CharField(max_length=100, help_text="组件别名")
    service_cname = models.CharField(max_length=100, default='', help_text="组件名")
    service_region = models.CharField(max_length=64, help_text="组件所属区")
    desc = models.CharField(max_length=200, null=True, blank=True, help_text="描述")
    category = models.CharField(max_length=15, help_text="组件分类：application,cache,store")
    service_port = models.IntegerField(help_text="组件端口", default=8000)
    is_web_service = models.BooleanField(default=False, blank=True, help_text="是否web组件")
    version = models.CharField(max_length=255, help_text="版本")
    update_version = models.IntegerField(default=1, help_text="内部发布次数")
    image = models.CharField(max_length=200, help_text="镜像")
    cmd = models.CharField(max_length=2048, null=True, blank=True, help_text="启动参数")
    setting = models.CharField(max_length=200, null=True, blank=True, help_text="设置项")
    extend_method = models.CharField(max_length=32, choices=extend_method, default='stateless', help_text="伸缩方式")
    env = models.CharField(max_length=200, null=True, blank=True, help_text="环境变量")
    min_node = models.IntegerField(help_text="启动个数", default=1)
    min_cpu = models.IntegerField(help_text="cpu个数", default=500)
    min_memory = models.IntegerField(help_text="内存大小单位（M）", default=256)
    container_gpu = models.IntegerField(help_text="gpu显存数量", default=0)
    inner_port = models.IntegerField(help_text="内部端口")
    volume_mount_path = models.CharField(max_length=200, null=True, blank=True, help_text="mount目录")
    host_path = models.CharField(max_length=300, null=True, blank=True, help_text="mount目录")
    deploy_version = models.CharField(max_length=20, null=True, blank=True, help_text="部署版本")
    code_from = models.CharField(max_length=20, null=True, blank=True, help_text="代码来源:gitlab,github")
    git_url = models.CharField(max_length=200, null=True, blank=True, help_text="code代码仓库")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    git_project_id = models.IntegerField(help_text="gitlab 中项目id", default=0)
    is_code_upload = models.BooleanField(default=False, blank=True, help_text="是否上传代码")
    code_version = models.CharField(max_length=100, null=True, blank=True, help_text="代码版本")
    service_type = models.CharField(max_length=50, null=True, blank=True, help_text="组件类型:web,mysql,redis,mongodb,phpadmin")
    delete_time = models.DateTimeField(auto_now_add=True)
    creater = models.IntegerField(help_text="组件创建者", default=0)
    language = models.CharField(max_length=40, null=True, blank=True, help_text="代码语言")
    protocol = models.CharField(max_length=15, help_text="服务协议：http,stream")
    total_memory = models.IntegerField(help_text="内存使用M", default=0)
    is_service = models.BooleanField(default=False, blank=True, help_text="是否inner组件")
    namespace = models.CharField(max_length=100, default='', help_text="镜像发布云帮的区间")
    volume_type = models.CharField(max_length=64, default='shared', help_text="共享类型shared、exclusive")
    port_type = models.CharField(max_length=15, default='multi_outer', help_text="端口类型，one_outer;dif_protocol;multi_outer")
    # 组件创建类型,cloud、assistant
    service_origin = models.CharField(max_length=15, default='assistant', help_text="组件创建类型cloud云市组件,assistant云帮组件")
    expired_time = models.DateTimeField(null=True, help_text="过期时间")
    service_source = models.CharField(max_length=15, default="source_code", null=True, blank=True, help_text="组件来源")
    create_status = models.CharField(max_length=15, null=True, blank=True, help_text="组件创建状态 creating|complete")
    update_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="更新时间")
    tenant_service_group_id = models.IntegerField(default=0, help_text="组件归属的组件组id")
    open_webhooks = models.BooleanField(default=False, help_text='是否开启自动触发部署功能(兼容老版本组件)')
    check_uuid = models.CharField(max_length=36, blank=True, null=True, default="", help_text="组件id")
    check_event_id = models.CharField(max_length=32, blank=True, null=True, default="", help_text="组件检测事件ID")
    docker_cmd = models.CharField(max_length=1024, null=True, blank=True, help_text="镜像创建命令")
    secret = models.CharField(max_length=64, null=True, blank=True, help_text="webhooks验证密码")
    server_type = models.CharField(max_length=5, default='git', help_text="源码仓库类型")
    is_upgrate = models.BooleanField(default=False, help_text='是否可以更新')
    build_upgrade = models.BooleanField(default=True, help_text='组件构建后是否升级')
    service_name = models.CharField(max_length=100, default='', help_text="组件名称（新加属性，数据中心使用）")


class TenantServiceLog(BaseModel):
    class Meta:
        db_table = 'tenant_service_log'

    user_id = models.IntegerField(help_text="用户id")
    user_name = models.CharField(max_length=40, help_text="用户名")
    service_id = models.CharField(max_length=32, help_text="组件id")
    tenant_id = models.CharField(max_length=32, help_text="租户id")
    action = models.CharField(max_length=15, help_text="分类：deploy,stop,restart")
    create_time = models.DateTimeField(auto_now=True, help_text="创建时间")


class TenantServiceRelation(BaseModel):
    class Meta:
        db_table = 'tenant_service_relation'
        unique_together = ('service_id', 'dep_service_id')

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    dep_service_id = models.CharField(max_length=32, help_text="依赖组件id")
    dep_service_type = models.CharField(max_length=50, null=True, blank=True, help_text="组件类型:web,mysql,redis,mongodb,phpadmin")
    dep_order = models.IntegerField(help_text="依赖顺序")


class TenantServiceEnv(BaseModel):
    class Meta:
        db_table = 'tenant_service_env'

    service_id = models.CharField(max_length=32, help_text="组件id")
    language = models.CharField(max_length=40, null=True, blank=True, help_text="代码语言")
    check_dependency = models.CharField(max_length=100, null=True, blank=True, help_text="检测运行环境依赖")
    user_dependency = models.CharField(max_length=1000, null=True, blank=True, help_text="用户自定义运行环境依赖")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")


class TenantServiceAuth(BaseModel):
    class Meta:
        db_table = 'tenant_service_auth'

    service_id = models.CharField(max_length=32, help_text="组件id")
    user = models.CharField(max_length=64, null=True, blank=True, help_text="用户")
    password = models.CharField(max_length=200, null=True, blank=True, help_text="密码")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")


class TenantServiceExtendMethod(BaseModel):
    class Meta:
        db_table = 'tenant_service_extend_method'

    service_key = models.CharField(max_length=32, help_text="组件key")
    version = models.CharField(max_length=20, null=False, help_text="当前最新版本")
    min_node = models.IntegerField(default=1, help_text="最小节点")
    max_node = models.IntegerField(default=20, help_text="最大节点")
    step_node = models.IntegerField(default=1, help_text="节点步长")
    min_memory = models.IntegerField(default=1, help_text="最小内存")
    max_memory = models.IntegerField(default=20, help_text="最大内存")
    step_memory = models.IntegerField(default=1, help_text="内存步长")
    is_restart = models.BooleanField(default=False, blank=True, help_text="是否重启")

    def to_dict(self):
        opts = self._meta
        data = {}
        for f in opts.concrete_fields:
            value = f.value_from_object(self)
            if isinstance(value, datetime):
                value = value.strftime('%Y-%m-%d %H:%M:%S')
            data[f.name] = value
        return data


class ServiceDomain(BaseModel):
    class Meta:
        db_table = 'service_domain'

    http_rule_id = models.CharField(max_length=128, unique=True, help_text="http_rule_id")
    region_id = models.CharField(max_length=36, help_text="region id")
    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    service_name = models.CharField(max_length=64, help_text="组件名")
    domain_name = models.CharField(max_length=128, help_text="域名")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    container_port = models.IntegerField(default=0, help_text="容器端口")
    protocol = models.CharField(max_length=15, default='http', help_text="域名类型 http https httptphttps httpandhttps")
    certificate_id = models.IntegerField(default=0, help_text='证书ID')
    domain_type = models.CharField(max_length=20, default='www', help_text="组件域名类型")
    service_alias = models.CharField(max_length=64, default='', help_text="组件别名")
    is_senior = models.BooleanField(default=False, help_text='是否有高级路由')
    domain_path = models.TextField(blank=True, help_text="域名path")
    domain_cookie = models.TextField(blank=True, help_text="域名cookie")
    domain_heander = models.TextField(blank=True, help_text="域名heander")
    type = models.IntegerField(default=0, help_text="类型（默认：0， 自定义：1）")
    the_weight = models.IntegerField(default=100, help_text="权重")
    rule_extensions = models.TextField(blank=True, help_text="扩展功能")
    is_outer_service = models.BooleanField(default=True, help_text="是否已开启对外端口")
    auto_ssl = models.BooleanField(default=False, help_text="是否自动匹配证书，升级为https，如果开启，由外部服务完成升级")
    auto_ssl_config = models.CharField(max_length=32, null=True, default=None, blank=True, help_text="自动分发证书配置")

    def __unicode__(self):
        return self.domain_name


class ServiceDomainCertificate(BaseModel):
    class Meta:
        db_table = 'service_domain_certificate'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    certificate_id = models.CharField(max_length=50, help_text="证书的唯一uuid")
    private_key = models.TextField(default='', help_text="证书key")
    certificate = models.TextField(default='', help_text='证书')
    certificate_type = models.TextField(default='', help_text='证书类型')
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    alias = models.CharField(max_length=64, help_text="证书别名")

    def __unicode__(self):
        return "private_key:{} certificate:{}".format(self.private_key, self.certificate)


class PermRelService(BaseModel):
    """
    用户和组件关系表/用户在一个组件中的角色
    """

    class Meta:
        db_table = 'service_perms'

    user_id = models.IntegerField(help_text="用户id")
    service_id = models.IntegerField(help_text="组件id")
    identity = models.CharField(max_length=15, choices=service_identity, help_text="组件身份", null=True, blank=True)
    role_id = models.IntegerField(help_text='角色', null=True, blank=True)


class PermRelTenant(BaseModel):
    """
    用户和团队的关系表
    identity ：租户权限
    """

    class Meta:
        db_table = 'tenant_perms'

    user_id = models.IntegerField(help_text="关联用户")
    tenant_id = models.IntegerField(help_text="团队id")
    identity = models.CharField(max_length=15, choices=tenant_identity, help_text="租户身份", null=True, blank=True)
    enterprise_id = models.IntegerField(help_text="关联企业")
    role_id = models.IntegerField(help_text='角色', null=True, blank=True)


class TenantRecharge(BaseModel):
    class Meta:
        db_table = 'tenant_recharge'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    user_id = models.IntegerField(help_text="充值用户")
    user_name = models.CharField(max_length=40, help_text="用户名")
    order_no = models.CharField(max_length=60, help_text="订单号")
    recharge_type = models.CharField(max_length=40, help_text="充值类型")
    money = models.DecimalField(max_digits=9, decimal_places=2, help_text="充值金额")
    subject = models.CharField(max_length=40, help_text="主题")
    body = models.CharField(max_length=80, help_text="详情")
    show_url = models.CharField(max_length=100, help_text="详情url")
    status = models.CharField(max_length=30, help_text="充值状态")
    trade_no = models.CharField(max_length=64, help_text="支付宝交易号")
    time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")


class TenantServiceStatics(BaseModel):
    class Meta:
        db_table = 'tenant_service_statics'
        unique_together = ('service_id', 'time_stamp')
        get_latest_by = 'ID'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    pod_id = models.CharField(max_length=32, help_text="组件id")
    node_num = models.IntegerField(help_text="节点个数", default=0)
    node_memory = models.IntegerField(help_text="节点内存k", default=0)
    container_cpu = models.IntegerField(help_text="cpu使用", default=0)
    container_memory = models.IntegerField(help_text="内存使用K", default=0)
    container_memory_working = models.IntegerField(help_text="正在使用内存K", default=0)
    pod_cpu = models.IntegerField(help_text="cpu使用", default=0)
    pod_memory = models.IntegerField(help_text="内存使用K", default=0)
    pod_memory_working = models.IntegerField(help_text="正在使用内存K", default=0)
    container_disk = models.IntegerField(help_text="磁盘使用K", default=0)
    storage_disk = models.IntegerField(help_text="磁盘使用K", default=0)
    net_in = models.IntegerField(help_text="网络使用K", default=0)
    net_out = models.IntegerField(help_text="网络使用K", default=0)
    flow = models.IntegerField(help_text="网络下载量", default=0)
    time_stamp = models.IntegerField(help_text="时间戳", default=0)
    status = models.IntegerField(default=0, help_text="0:无效；1:有效；2:操作中")
    region = models.CharField(max_length=64, help_text="组件所属区")
    time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")


class TenantConsumeDetail(BaseModel):
    class Meta:
        db_table = 'tenant_consume_detail'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    service_alias = models.CharField(max_length=100, help_text="组件别名")
    node_num = models.IntegerField(help_text="节点个数", default=0)
    cpu = models.IntegerField(help_text="cpu使用", default=0)
    memory = models.IntegerField(help_text="内存使用K", default=0)
    disk = models.IntegerField(help_text="磁盘使用K", default=0)
    net = models.IntegerField(help_text="网络使用K", default=0)
    money = models.DecimalField(max_digits=9, decimal_places=2, help_text="消费金额", default=0)
    total_memory = models.IntegerField(help_text="内存使用K", default=0)
    fee_rule = models.CharField(max_length=60, help_text="计费规则")
    pay_status = models.CharField(max_length=10, help_text="扣费状态；payed,unpayed")
    region = models.CharField(max_length=15, help_text="组件所属区")
    status = models.IntegerField(help_text="组件状态", default=1)
    time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")


class TenantConsume(BaseModel):
    class Meta:
        db_table = 'tenant_consume'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    total_memory = models.IntegerField(help_text="内存使用K", default=0)
    cost_money = models.DecimalField(max_digits=9, decimal_places=2, help_text="消费金额", default=0)
    payed_money = models.DecimalField(max_digits=9, decimal_places=2, help_text="消费金额", default=0)
    pay_status = models.CharField(max_length=10, help_text="扣费状态；payed,unpayed")
    time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")


class TenantFeeBill(BaseModel):
    class Meta:
        db_table = 'tenant_fee_bill'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    bill_title = models.CharField(max_length=100, help_text="发票标题")
    bill_type = models.CharField(max_length=10, help_text="公司或个人")
    bill_address = models.CharField(max_length=100, help_text="邮寄地址")
    bill_phone = models.CharField(max_length=100, help_text="邮寄电话")
    money = models.DecimalField(max_digits=9, decimal_places=2, help_text="发票金额")
    status = models.CharField(max_length=10, help_text="审核状态:已审核(approved)，未审核(unapproved)")
    time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")


class TenantPaymentNotify(BaseModel):
    class Meta:
        db_table = 'tenant_payment_notify'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    notify_type = models.CharField(max_length=10, help_text="通知类型：余额不足，欠费,资源已超限")
    notify_content = models.CharField(max_length=200, help_text="通知类容")
    send_person = models.CharField(max_length=20, help_text="通知人")
    time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    status = models.CharField(max_length=10, help_text="有效(valid),无效(unvalid)")


class PhoneCode(BaseModel):
    class Meta:
        db_table = 'phone_code'

    phone = models.CharField(max_length=11, help_text="手机号码")
    type = models.CharField(max_length=10, help_text="类型")
    code = models.CharField(max_length=10, help_text="类型")
    message_id = models.CharField(max_length=100, help_text="aliyun发送的message_id")
    status = models.IntegerField(help_text='发送状态0已发送1发送成功2发送失败', default=0)
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")


class TenantRegionPayModel(BaseModel):
    class Meta:
        db_table = 'tenant_region_pay_model'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    region_name = models.CharField(max_length=20, help_text="区域中心名称")
    pay_model = models.CharField(max_length=10, default='hour', help_text="付费模式:hour,month,year")
    buy_period = models.IntegerField(help_text="购买周期", default=0)
    buy_memory = models.IntegerField(help_text="购买内存", default=0)
    buy_disk = models.IntegerField(help_text="购买磁盘", default=0)
    buy_net = models.IntegerField(help_text="购买流量", default=0)
    buy_start_time = models.DateTimeField(help_text="购买开始时间")
    buy_end_time = models.DateTimeField(help_text="购买结束时间")
    buy_money = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, help_text="购买金额")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")


class TenantServiceL7Info(BaseModel):
    class Meta:
        db_table = 'tenant_l7_info'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, db_index=True, help_text="组件id")
    dep_service_id = models.CharField(max_length=32, help_text="依赖组件id")
    l7_json = models.CharField(max_length=255, help_text="高级组件特性信息")


class TenantServiceEnvVar(BaseModel):
    class Meta:
        db_table = 'tenant_service_env_var'

    class ScopeType(Enum):
        """范围"""
        OUTER = "outer"
        INNER = "inner"

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, db_index=True, help_text="组件id")
    container_port = models.IntegerField(default=0, help_text="端口")
    name = models.CharField(max_length=1024, blank=True, help_text="名称")
    attr_name = models.CharField(max_length=1024, help_text="属性")
    attr_value = models.TextField(help_text="值")
    is_change = models.BooleanField(default=False, blank=True, help_text="是否可改变")
    scope = models.CharField(max_length=10, help_text="范围", default=ScopeType.OUTER.value)
    create_time = models.DateTimeField(auto_now_add=True, help_text="创建时间")

    def __unicode__(self):
        return self.name

    def is_port_env(self):
        return self.container_port != 0

    def is_host_env(self):
        return self.container_port != 0 and self.attr_name.endswith("_HOST")


class TenantServicesPort(BaseModel):
    class Meta:
        db_table = 'tenant_services_port'
        unique_together = ('service_id', 'container_port')

    tenant_id = models.CharField(max_length=32, null=True, blank=True, help_text='租户id')
    service_id = models.CharField(max_length=32, db_index=True, help_text="组件ID")
    container_port = models.IntegerField(default=0, help_text="容器端口")
    mapping_port = models.IntegerField(default=0, help_text="映射端口")
    lb_mapping_port = models.IntegerField(default=0, help_text="负载均衡映射端口")
    protocol = models.CharField(max_length=15, default='', blank=True, help_text="组件协议：http,stream")
    port_alias = models.CharField(max_length=64, default='', blank=True, help_text="port别名")
    is_inner_service = models.BooleanField(default=False, blank=True, help_text="是否内部组件；0:不绑定；1:绑定")
    is_outer_service = models.BooleanField(default=False, blank=True, help_text="是否外部组件；0:不绑定；1:绑定")
    k8s_service_name = models.CharField(max_length=63, blank=True, help_text="the name of kubernetes service")


class TenantServiceMountRelation(BaseModel):
    class Meta:
        db_table = 'tenant_service_mnt_relation'
        unique_together = ('service_id', 'dep_service_id', 'mnt_name')

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    dep_service_id = models.CharField(max_length=32, help_text="依赖组件id")
    mnt_name = models.CharField(max_length=100, help_text="mnt name")
    mnt_dir = models.CharField(max_length=400, help_text="mnt dir")

    def key(self):
        return self.service_id + self.dep_service_id + self.mnt_name


class TenantServiceVolume(BaseModel):
    """数据持久化表格"""

    class Meta:
        db_table = 'tenant_service_volume'

    SHARE = 'share-file'
    LOCAL = 'local'
    TMPFS = 'memoryfs'
    CONFIGFILE = 'config-file'

    service_id = models.CharField(max_length=32, help_text="组件id")
    category = models.CharField(max_length=50, blank=True, help_text="组件类型")
    host_path = models.CharField(max_length=400, help_text="物理机的路径,绝对路径")
    volume_type = models.CharField(max_length=64, blank=True)
    volume_path = models.CharField(max_length=400, help_text="容器内路径,application为相对;其他为绝对")
    volume_name = models.CharField(max_length=100, blank=True)
    volume_capacity = models.IntegerField(default=0, help_text="存储大小，单位(Mi)")
    volume_provider_name = models.CharField(max_length=100, null=True, blank=True, help_text="存储驱动名字")
    access_mode = models.CharField(max_length=100, null=True, blank=True, help_text="读写模式：RWO、ROX、RWX")
    share_policy = models.CharField(max_length=100, null=True, default='', blank=True, help_text="共享模式")
    backup_policy = models.CharField(max_length=100, null=True, default='', blank=True, help_text="备份策略")
    reclaim_policy = models.CharField(max_length=100, null=True, default='', blank=True, help_text="回收策略")
    allow_expansion = models.NullBooleanField(max_length=100, null=True, default=0, blank=True, help_text="只是支持控制扩展，0：不支持；1：支持")


class TenantServiceConfigurationFile(BaseModel):
    """组件配置文件"""

    class Meta:
        db_table = 'tenant_service_config'

    service_id = models.CharField(max_length=32, help_text="组件id")
    volume_id = models.IntegerField(null=True, help_text="存储id")
    volume_name = models.CharField(max_length=32, null=True, help_text="组件名称, 唯一标识")
    file_content = models.TextField(blank=True, help_text="配置文件内容")


class ServiceGroup(BaseModel):
    """组件分组（应用）"""

    class Meta:
        db_table = 'service_group'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    group_name = models.CharField(max_length=128, help_text="组名")
    region_name = models.CharField(max_length=64, help_text="区域中心名称")
    is_default = models.BooleanField(default=False, help_text="默认组件")
    order_index = models.IntegerField(default=0, help_text="应用排序")
    note = models.CharField(max_length=2048, null=True, blank=True, help_text="备注")
    username = models.CharField(max_length=255, null=True, blank=True, help_text="the username of principal")
    governance_mode = models.CharField(
        max_length=255,
        null=True,
        blank=True,
        default=GovernanceModeEnum.BUILD_IN_SERVICE_MESH.name,
        help_text="governance mode")
    create_time = models.DateTimeField(help_text="创建时间")
    update_time = models.DateTimeField(help_text="更新时间")
    app_type = models.CharField(max_length=255, default="rainbond", help_text="应用类型")
    app_store_name = models.CharField(max_length=255, null=True, blank=True, help_text="应用商店名称")
    app_store_url = models.CharField(max_length=255, null=True, blank=True, help_text="应用商店 URL")
    app_template_name = models.CharField(max_length=255, null=True, blank=True, help_text="应用模板名称")
    version = models.CharField(max_length=255, null=True, blank=True, help_text="Helm 应用版本")

    @property
    def app_id(self):
        return self.ID

    @property
    def app_name(self):
        return self.group_name


class ServiceGroupRelation(BaseModel):
    """组件与分组关系"""

    class Meta:
        db_table = 'service_group_relation'

    service_id = models.CharField(max_length=32, help_text="组件id")
    group_id = models.IntegerField()
    tenant_id = models.CharField(max_length=32, help_text="租户id")
    region_name = models.CharField(max_length=64, help_text="区域中心名称")


class RegionApp(BaseModel):
    """the dependencies between region app and console app"""

    class Meta:
        db_table = 'region_app'
        unique_together = ('region_name', 'region_app_id', 'app_id')

    region_name = models.CharField(max_length=64, help_text="region name")
    region_app_id = models.CharField(max_length=32, help_text="region app id")
    app_id = models.IntegerField()


class ImageServiceRelation(BaseModel):
    """image_url拉取的service的对应关系"""

    class Meta:
        db_table = 'tenant_service_image_relation'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    image_url = models.CharField(max_length=200, help_text="镜像地址")
    service_cname = models.CharField(max_length=100, default='', help_text="组件名")


class ComposeServiceRelation(BaseModel):
    """docker compose 文件"""

    class Meta:
        db_table = 'tenant_compose_file'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    compose_file_id = models.CharField(max_length=32, help_text="compose文件id")
    compose_file = models.FileField(upload_to=compose_file_path, null=True, blank=True, help_text="compose file")


class ServiceRule(BaseModel):
    """用户组件自动伸缩规则 """

    class Meta:
        db_table = 'tenant_service_rule'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    tenant_name = models.CharField(max_length=40, unique=True, help_text="租户名称")
    service_id = models.CharField(max_length=32, help_text="组件id")
    service_alias = models.CharField(max_length=100, help_text="组件别名")
    service_region = models.CharField(max_length=64, help_text="数据中心")
    item = models.CharField(max_length=50, help_text="规则项目")
    maxvalue = models.IntegerField(default=0)
    minvalue = models.IntegerField(default=0)
    status = models.BooleanField(default=False, blank=True, help_text="是否生效；0:停止；1:生效")
    count = models.IntegerField(default=0)
    node_number = models.IntegerField(help_text="实例启动个数", default=1)
    port = models.CharField(max_length=10)
    port_type = models.CharField(max_length=15, default='multi_outer', help_text="端口类型，one_outer;dif_protocol;multi_outer")


class ServiceRuleHistory(BaseModel):
    """用户组件自动伸缩规则触发历史 """

    class Meta:
        db_table = 'tenant_service_rule_history'

    rule_id = models.CharField(max_length=32, help_text="规则id")
    trigger_time = models.CharField(max_length=100, help_text="触发时间")
    action = models.CharField(max_length=10, help_text="触发动作")
    message = models.CharField(max_length=1024, help_text="描述")


class ServiceAttachInfo(BaseModel):
    """组件配套信息"""

    class Meta:
        db_table = 'service_attach_info'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    memory_pay_method = models.CharField(max_length=32, choices=pay_method)
    disk_pay_method = models.CharField(max_length=32, choices=pay_method)
    min_memory = models.IntegerField(help_text="内存大小单位（M）", default=128)
    min_node = models.IntegerField(help_text="节点个数", default=1)
    disk = models.IntegerField(help_text='磁盘大小')
    pre_paid_period = models.IntegerField(help_text="预付费项目购买时长(单位:月)", default=0)
    pre_paid_money = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, help_text="预付费金额")
    buy_start_time = models.DateTimeField(help_text="购买开始时间")
    buy_end_time = models.DateTimeField(help_text="购买结束时间")
    create_time = models.DateTimeField(auto_now_add=True, help_text="创建时间")
    region = models.CharField(max_length=64, help_text="数据中心")

    def toJSON(self):
        data = {}
        for f in self._meta.fields:
            obj = getattr(self, f.name)
            if type(f.name) == DateTimeField:
                data[f.name] = obj.strftime('%Y-%m-%d %H:%M:%S')
            else:
                data[f.name] = obj
        return data


class ServiceCreateStep(BaseModel):
    class Meta:
        db_table = 'service_create_step'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    app_step = models.IntegerField(default=1, help_text="创建组件的步数")


pay_status = (
    ("已发布", 'payed'),
    ("测试中", "unpayed"),
)


class ServiceFeeBill(BaseModel):
    class Meta:
        db_table = 'service_fee_bill'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    prepaid_money = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, help_text="付费金额")
    pay_status = models.CharField(max_length=15, choices=pay_status, help_text="付费状态")
    cost_type = models.CharField(max_length=15, help_text="消费类型")
    node_memory = models.IntegerField(help_text="内存大小单位（M）", default=128)
    node_num = models.IntegerField(help_text="节点个数", default=1)
    disk = models.IntegerField(help_text='磁盘大小')
    buy_period = models.IntegerField(help_text="预付费时长(单位:小时)", default=0)
    create_time = models.DateTimeField(auto_now_add=True, help_text="创建时间")
    pay_time = models.DateTimeField(auto_now_add=True, help_text="支付时间")


class ServiceConsume(BaseModel):
    class Meta:
        db_table = 'service_consume'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    memory = models.IntegerField(help_text="内存大小单位（M）", default=0)
    node_num = models.IntegerField(help_text="节点个数", default=1)
    disk = models.IntegerField(help_text='磁盘大小', default=0)
    net = models.IntegerField(help_text="网络使用K", default=0)
    memory_money = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, help_text="内存金额")
    disk_money = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, help_text="磁盘金额")
    net_money = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, help_text="网络金额")
    pay_money = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, help_text="实际付费金额")
    pay_status = models.CharField(max_length=15, choices=pay_status, help_text="付费状态")
    region = models.CharField(max_length=64, help_text="数据中心")
    status = models.IntegerField(default=0, help_text="0:无效；1:有效；2:操作中")
    time = models.DateTimeField(help_text="创建时间")
    real_memory_money = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, help_text="内存按需金额")
    real_disk_money = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, help_text="磁盘按需金额")


class ServiceEvent(BaseModel):
    class Meta:
        db_table = 'service_event'

    event_id = models.CharField(max_length=32, help_text="操作id")
    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    user_name = models.CharField(max_length=64, help_text="操作用户")
    start_time = models.DateTimeField(help_text="操作开始时间")
    end_time = models.DateTimeField(help_text="操作结束时间", null=True)
    type = models.CharField(max_length=20, help_text="操作类型")
    status = models.CharField(max_length=20, help_text="操作处理状态 success failure")
    final_status = models.CharField(max_length=20, default="", help_text="操作状态，complete or timeout or null")
    message = models.TextField(help_text="操作说明")
    deploy_version = models.CharField(max_length=20, help_text="部署版本")
    old_deploy_version = models.CharField(max_length=20, help_text="历史部署版本")
    code_version = models.CharField(max_length=200, help_text="部署代码版本")
    old_code_version = models.CharField(max_length=200, help_text="历史部署代码版本")
    region = models.CharField(max_length=64, default="", help_text="组件所属数据中心")


class GroupCreateTemp(BaseModel):
    class Meta:
        db_table = 'group_create_temp'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    service_key = models.CharField(max_length=32, help_text="组件key")
    share_group_id = models.IntegerField(help_text="组件组发布id")
    service_group_id = models.IntegerField(help_text="组件所属组")
    service_cname = models.CharField(max_length=100, default='', help_text="组件名")


class BackServiceInstallTemp(BaseModel):
    class Meta:
        db_table = "back_service_install_temp"

    group_share_id = models.CharField(max_length=32, unique=True, help_text="组件组发布id")
    share_pk = models.IntegerField(help_text="发布的组件组PK 对应app_service_group中的ID")
    group_pk = models.IntegerField(help_text="组件所在组ID")
    success = models.BooleanField(default=True, help_text="成功安装")


class ServiceProbe(BaseModel):
    class Meta:
        db_table = 'service_probe'

    service_id = models.CharField(max_length=32, help_text="组件id")
    probe_id = models.CharField(max_length=32, help_text="探针id")
    mode = models.CharField(max_length=20, help_text="不健康处理方式readiness（下线）或liveness（重启）或ignore（忽略）")
    scheme = models.CharField(max_length=10, default="tcp", help_text="探针使用协议,tcp,http,cmd")
    path = models.CharField(max_length=200, default="", help_text="路径")
    port = models.IntegerField(default=80, help_text="检测端口")
    cmd = models.CharField(max_length=1024, default="", help_text="cmd 命令")
    http_header = models.CharField(max_length=300, blank=True, default="", help_text="http请求头，key=value,key2=value2")
    initial_delay_second = models.IntegerField(default=4, help_text="初始化等候时间")
    period_second = models.IntegerField(default=3, help_text="检测间隔时间")
    timeout_second = models.IntegerField(default=5, help_text="检测超时时间")
    failure_threshold = models.IntegerField(default=3, help_text="标志为失败的检测次数")
    success_threshold = models.IntegerField(default=1, help_text="标志为成功的检测次数")
    is_used = models.BooleanField(default=1, help_text="是否启用")


class ConsoleConfig(BaseModel):
    class Meta:
        db_table = 'console_config'

    key = models.CharField(max_length=100, help_text="配置名称")
    value = models.CharField(max_length=1000, help_text="配置值")
    description = models.TextField(null=True, blank=True, default="", help_text="说明")
    update_time = models.DateTimeField(help_text="更新时间", null=True)


class ServicePaymentNotify(BaseModel):
    class Meta:
        db_table = "service_payment_notify"

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    notify_type = models.CharField(max_length=10, help_text="通知类型")
    notify_content = models.CharField(max_length=200, help_text="通知内容")
    send_person = models.CharField(max_length=20, help_text="通知内容")
    time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    end_time = models.DateTimeField(blank=True, help_text="删除截止时间")
    status = models.CharField(max_length=10, help_text="状态")


class TenantEnterprise(BaseModel):
    class Meta:
        db_table = 'tenant_enterprise'

    enterprise_id = models.CharField(max_length=32, unique=True, help_text="企业id")
    enterprise_name = models.CharField(max_length=64, help_text="企业名称")
    enterprise_alias = models.CharField(max_length=64, blank=True, null=True, default='', help_text="企业别名")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, null=True, help_text="创建时间")
    enterprise_token = models.CharField(max_length=256, blank=True, null=True, default='', help_text="企业身份token")
    is_active = models.IntegerField(default=0, help_text="是否在云市上激活, 0:未激活, 1:已激活")
    logo = models.CharField(max_length=128, blank=True, null=True, default='', help_text="企业logo")

    def __unicode__(self):
        return self.to_dict()


class TenantEnterpriseToken(BaseModel):
    class Meta:
        db_table = 'tenant_enterprise_token'
        unique_together = ('enterprise_id', 'access_target')

    enterprise_id = models.IntegerField(default=0, help_text="企业id")
    access_target = models.CharField(max_length=32, blank=True, null=True, default='', help_text="要访问的目标组件名称")
    access_url = models.CharField(max_length=255, help_text="需要访问的api地址")
    access_id = models.CharField(max_length=32, help_text="target分配给客户端的ID")
    access_token = models.CharField(max_length=256, blank=True, null=True, default='', help_text="客户端token")
    crt = models.TextField(default='', blank=True, null=True, help_text="客户端证书")
    key = models.TextField(default='', blank=True, null=True, help_text="客户端证书key")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, null=True, help_text="创建时间")
    update_time = models.DateTimeField(auto_now_add=True, blank=True, null=True, help_text="更新时间")

    def __unicode__(self):
        return self.to_dict()


class TenantServiceGroup(BaseModel):
    """从应用模型安装的组件从属关系记录"""

    class Meta:
        db_table = 'tenant_service_group'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    group_name = models.CharField(max_length=64, help_text="组件组名")
    group_alias = models.CharField(max_length=64, help_text="组件别名")
    group_key = models.CharField(max_length=32, help_text="组件组id")
    group_version = models.CharField(max_length=32, help_text="组件组版本")
    region_name = models.CharField(max_length=64, help_text="区域中心名称")
    service_group_id = models.IntegerField(default=0, help_text="安装时所属应用的主键ID")


class ServiceTcpDomain(BaseModel):
    """Tcp/Udp策略"""

    class Meta:
        db_table = 'service_tcp_domain'

    tcp_rule_id = models.CharField(max_length=128, unique=True, help_text="tcp_rule_id")
    region_id = models.CharField(max_length=36, help_text="region id")
    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    service_name = models.CharField(max_length=64, help_text="组件名")
    end_point = models.CharField(max_length=256, help_text="ip+port")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, help_text="创建时间")
    protocol = models.CharField(max_length=15, default='', blank=True, help_text="服务协议：tcp,udp")
    container_port = models.IntegerField(default=0, help_text="容器端口")
    service_alias = models.CharField(max_length=64, default='', help_text="组件别名")
    type = models.IntegerField(default=0, help_text="类型（默认：0， 自定义：1）")
    rule_extensions = models.TextField(null=True, blank=True, help_text="扩展功能")
    is_outer_service = models.BooleanField(default=True, help_text="是否已开启对外端口")


class ThirdPartyServiceEndpoints(BaseModel):
    """第三方组件endpoints"""

    class Meta:
        db_table = 'third_party_service_endpoints'

    tenant_id = models.CharField(max_length=32, help_text="租户id")
    service_id = models.CharField(max_length=32, help_text="组件id")
    service_cname = models.CharField(max_length=128, help_text="组件名")
    endpoints_info = models.TextField(help_text="endpoints信息")
    endpoints_type = models.CharField(max_length=32, help_text="类型（static-静态， api， discovery-服务发现）")


class ServiceWebhooks(BaseModel):
    """组件的自动部署属性"""

    class Meta:
        db_table = 'service_webhooks'

    service_id = models.CharField(max_length=32, help_text="组件id")
    state = models.BooleanField(default=False, help_text="状态（开启，关闭）")
    webhooks_type = models.CharField(max_length=128, help_text="webhooks类型（image_webhooks, code_webhooks, api_webhooks）")
    deploy_keyword = models.CharField(max_length=128, default='deploy', help_text="触发自动部署关键字")
    trigger = models.CharField(max_length=256, default='', help_text="触发正则表达式")


class GatewayCustomConfiguration(BaseModel):
    """网关自定义参数配置"""

    class Meta:
        db_table = 'gateway_custom_configuration'

    rule_id = models.CharField(max_length=32, unique=True, help_text="规则id")
    value = models.TextField(help_text="配置value")
